#include"socket.hpp"

#include<fcntl.h>

#include<poll.h>

#include<sys/select.h>

int defaultfd = -1;
short defaultevent = 0;

class pollserver
{
public:
    pollserver()
    {
        for(int i = 0; i < POLL_SIZE; ++i)
        {
            _pf_arr[i].fd = defaultfd;
            _pf_arr[i].events = defaultevent;
            _pf_arr[i].revents = defaultevent;
        }
        _pa_size = 0;
    }
    void init()
    {
        _sk.my_socket();
        _sk.my_bind("0.0.0.0", 8080);
        _sk.my_listen();
        _pf_arr[_pa_size].fd = _sk.get_sockfd();
        _pf_arr[_pa_size].events = POLLIN;
        ++_pa_size;
    }

    void event_hander()
    {
        char buffer[1024] = {0};
        for(int i = 0; i <= _pa_size; ++i)
        {
            if(_pf_arr[i].revents == POLLIN)
            {
                if(_pf_arr[i].fd == _sk.get_sockfd())
                {
                    std::cout << "get a new accept" << std::endl;
                    std::string clientip;
                    int16_t port = 0;
                    int acc_fd = _sk.my_accept(clientip, port); // accept时，事件已经就绪，不用等待啦
                    if(_pa_size >= POLL_SIZE) // 这里设置的静态数组，所以有容量，可以设置成动态的这样就不会有容量了，可以一直添加
                    {
                        std::cout << "out of the range of poll, can not accept" << std::endl;
                        close(acc_fd);
                    }
                    else // 可以遍历找失效的pollfd结构体，这里图省事就没有搞
                    {
                        _pf_arr[_pa_size].fd = acc_fd;
                        _pf_arr[_pa_size].events = POLLIN;
                        ++_pa_size;
                    }
                }
                else
                {
                    ssize_t n = read(_pf_arr[i].fd, buffer, sizeof(buffer)); // 读的时候，事件已经就绪，不用等待啦
                    if(n < 0)
                    {
                        perror("read");
                        return;
                    }
                    else if(n == 0)
                    {
                        std::cout << "fd " << _pf_arr[i].fd << " is closed, close it and back." << std::endl;
                        close(_pf_arr[i].fd);
                        _pf_arr[i].fd = defaultfd; // fd为负数poll会直接忽略，相当于移除了，因为直接挪动成本太高
                        return;
                    }
                    else
                    {
                        buffer[n] = 0;
                        std::cout << "get a message : " << buffer;
                        write(_pf_arr[i].fd, buffer, n);
                    }
                }
            }
        }
    }

    void start()
    {
        while(1)
        {
            int n = poll(_pf_arr, POLL_SIZE, 5000);
            if(n < 0)
            {
                perror("poll");
                return;
            }
            else if(n == 0)
            {
                std::cout << "time out" << std::endl;
            }
            else
            {
                event_hander();
            }
        }
    }
private:
    sock _sk;
    static const int POLL_SIZE = 4096;
    struct pollfd _pf_arr[POLL_SIZE];
    int _pa_size = 0;
};